package org.example.v1.registry;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.example.v1.protocol.RpcInvokeProtocol;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class RegistryHandler extends ChannelInboundHandlerAdapter {
    private List<String> classNames = new ArrayList<>();
    private Map<String, Object> serviceMap = new ConcurrentHashMap<>();

    public RegistryHandler() {
        // 加载文件,正常的是读取配置文件
        scannerFiles("org.example.v1.provider");
        // 注册
        doRegisty();
    }

    private void doRegisty() {
        if (classNames == null) {
            return;
        }
        try {
            for (String className : classNames) {
                Class<?> clazz = Class.forName(className);
                Class<?> interfaceCls = clazz.getInterfaces()[0];
                String serviceName = interfaceCls.getName();
                serviceMap.put(serviceName, clazz.newInstance());
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private void scannerFiles(String packageName) {
        URL url = this.getClass().getClassLoader().getResource(packageName.replaceAll("\\.", "/"));
        File files = new File(url.getFile());
        for (File file : files.listFiles()) {
            if (file.isDirectory()) {
                scannerFiles(file.getName());
            } else {
                classNames.add(packageName + "." + file.getName().replace(".class", ""));
            }
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof RpcInvokeProtocol) {
            RpcInvokeProtocol request = (RpcInvokeProtocol) msg;
            if (serviceMap.containsKey(request.getClassName())) {
                Object service = serviceMap.get(request.getClassName());
                Method method = service.getClass().getMethod(request.getMethodName(), request.getParams());
                Object result = method.invoke(service, request.getValues());
                ctx.writeAndFlush(result);
                ctx.close();
            }
        }

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("registry request exception");
    }
}
